﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Microsoft.Practices.Unity.InterceptionExtension;

namespace Luminji.Core.Enterprise.RBAC
{
    public class AuthorityHandler : ICallHandler
    {
        /// <summary>
        /// Invoke order
        /// </summary>
        public int Order { get; set; }

        //public static List<Role> Roles { private get; set; }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            MethodBase mb = input.MethodBase;
            object[] attrObj = mb.GetCustomAttributes(typeof(TaskAttribute), false);
            IAuthority biz = input.Target as IAuthority;
            IUser currentUser = biz.CurrentUser;
            if (attrObj == null)
            {
                throw new ArgumentException("TaskAttribute should be defined with the AuthorityAttribute");
            }
            else
            {
                TaskAttribute attr = (TaskAttribute)attrObj[0];
                if (!string.IsNullOrEmpty(attr.TaskName))
                {
                    if (currentUser.CurrentUserRoles == null)
                    {
                        throw new ArgumentException("Roles property should be set first");
                    }
                    string taskName = attr.TaskName;

                    foreach (Role currentUserRole in currentUser.CurrentUserRoles)
                    {
                        IEnumerable<TaskAttribute> tasks = from p in currentUserRole.Tasks
                                                           where p.TaskName == taskName
                                                           select p;
                        if (tasks.Count() > 0)
                        {
                            var retvalue = getNext()(input, getNext);
                            return retvalue;
                        }
                    }
                    
                    //else throw exception
                    throw new UnauthorizedAccessException("access denied");
                }
            }
            return null;
        }
    }
}
